package gam.t1.appraisal2.dinv.sys;

import com.google.common.collect.Maps;
import gam.t1.appraisal2.dinv.AppraisalOption;
import gam.t1.appraisal2.dinv.DataInventory;
import gam.t1.appraisal2.dinv.view.CollectionsView;
import gam.t1.appraisal2.dinv.view.View2DCoordinate;
import gam.t1.appraisal2.dinv.view.impl.ClickBlock;
import gam.t1.appraisal2.dinv.view.impl.ClickBlockCollections;
import org.bukkit.inventory.ItemStack;

import java.util.Map;
import java.util.Objects;
import java.util.function.Function;

public class PageSystem<T extends DataInventory> extends ClickBlockCollections<PageSystem<T>> {
    private int allPageSize;
    private int currentPageSize;
    private final T h;
    private PageView<T> view;
    private PageController<T> controller;

    public PageSystem(T handler,int x,int y,int maxSize, PageView view, PageController controller) {
        this(handler,maxSize,view,controller);
        setCoordinate(new View2DCoordinate(x,y));
    }
    public PageSystem(T handler,int maxSize,PageView<T> view,PageController<T> controller) {
        super(handler);
        this.h = handler;
        this.view = view;
        this.controller = controller;
        this.allPageSize = maxSize <= 0 ? 1: maxSize;
        this.currentPageSize = 1;

    }
    public void up(){
        currentPageSize--;
    }
    public void down(){
        currentPageSize++;
    }
    public boolean hasNext(){
        return currentPageSize < allPageSize;
    }
    public boolean hasPrevious(){
        return currentPageSize > 1;
    }
    public int currentPageSize() {
        return currentPageSize;
    }
    public void setAllPageSize(int allPageSize) {this.allPageSize = (int) Math.ceil(allPageSize / (double) getView().a().length);}
    @Override
    public ClickBlock<PageSystem<T>> getClickBlock(int in) {
        ClickBlock<PageSystem<T>> v = getView().getClickBlock(in);
        ClickBlock<PageSystem<T>> v2 = getController().getClickBlock(in);
        return v != null ? v : v2;
    }
    @Override
    public Map<Integer, ItemStack> getStorageStacks(CollectionsView main) {
        Map<Integer, ItemStack> v1 = Maps.newHashMap();
        v1.putAll(getView().getStorageStacks(this));
        v1.putAll(getController().getStorageStacks(this));
        return v1;
    }
    public T getHandle() {
        return h;
    }
    public void setView(PageView<T> view) {
        this.view = view;
        setAllPageSize(allPageSize);
    }
    public void setController(PageController<T> controller) {
        this.controller = controller;
    }
    public PageView<T> getView() {
        return view;
    }
    public PageController<T> getController() {
        return controller;
    }
    public static final class PageView<T extends DataInventory> extends ClickBlockCollections<PageSystem<T>>{
        private final int[] a;
        private int b = 0;
        public PageView(PageSystem<T> handler1, int[] items, Function<PageSystem<T>, ItemStack> f) {
            super(handler1.getHandle());
            Objects.requireNonNull(items, "items is null");
            this.a = items;
            for (int item : items) register(item, cV -> false,f);
        }
        public int[] a() {
            return a;
        }
        public int b() {
            return b;
        }
        public void c(){
            b++;
            if (b >= a.length) d();
        }
        public void d(){
            b = -1;
        }
        public void e() { b = 0; }
    }
    public static final class PageController<T extends DataInventory> extends ClickBlockCollections<PageSystem<T>>{
        private final PageSystem<T> a;
        public PageController(PageSystem<T> handler1, int left,int right) {
            super(handler1.getHandle());
            this.a = handler1;
            register(left,cV -> {
                if (a.hasPrevious()) {
                    a.up();
                    handler1.getView().e();
                    return true;
                }
                return false;
            },pS -> pS.hasPrevious() ? AppraisalOption.HASPre : AppraisalOption.NO);
            register(right,cV -> {
                if (a.hasNext()) {
                    a.down();
                    handler1.getView().e();
                    return true;
                }
                return false;
            },pS -> pS.hasNext() ? AppraisalOption.HASNext : AppraisalOption.NO);
        }
    }
}
